import datamodel
import event_hub

from google.appengine.api import channel
from google.appengine.api import prospective_search
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template


class RestrictedPage(webapp.RequestHandler):

  def get_safe(self, template_values):
    pass

  def get(self):
    user = users.get_current_user()
    if not user:
      self.redirect(users.create_login_url(self.request.uri))
      return
    self.player = datamodel.Player.get(user=user)
    template_values = {'player_token': channel.create_channel(self.player.get_id()),
                       'alias': self.player.alias,
                       'player_id': self.player.get_id()}
    self.get_safe(template_values)


class MainPage(RestrictedPage):
  def get_safe(self, template_values):
    self.response.out.write(template.render('templates/overview.html', template_values))


class DaoPage(RestrictedPage):

  def __init__(self):
    self.req_trans = {
                      'event-listen': self.listen,
                      'player-list': self.list_players,
                      'player-update': self.update_player,
                      'score-add': self.add_score,
                      'score-list': self.list_scores,
                      'friends-list': self.list_friends,
                      'friends-add':  self.add_friend,
                      'friends-accept':  self.accept_friend,
                      'friends-reject':  self.remove_friend,
                      'friends-remove':  self.remove_friend,
                     }

  def listen(self):
    client_id = 'query' + self.player.get_id()
    event_hub.register_query(datamodel.PlayerEvent, self.request.get('query'), client_id)
    if self.request.get('new_token'):
      self.response.out.write(channel.create_channel(client_id));

  def add_score(self):
    player_id = self.request.get('player_id')
    game = self.request.get('game')
    time = int(self.request.get('time'))
    score = int(self.request.get('score'))

    if (not player_id or
        not game or
        not time or
        not score):
      self.response.set_status(400)
      self.response.out.write('Invalid Request')
      return

    datamodel.PlayerScore.record(player_id, game, time, score)

  def list_scores(self):
    game = self.request.get('game')
    board = self.request.get('board')
    cat = self.request.get('cat')
    if (not game):
      self.response.set_status(400)
      self.response.out.write('Invalid Request')
      return

    if cat == 'best_time':
      if board == 'all' :
        scores, query = datamodel.PlayerScore.get_best_times(game, 5)
      elif board == 'today':
        scores, query = datamodel.PlayerScore.get_best_times(game, 5, True)
      else:  # default to 'friends'
        scores, query = datamodel.PlayerScore.get_best_friend_times(self.player.get_id(), game, 5)
    else:  # default to 'high_score'
      if board == 'all' :
        scores, query = datamodel.PlayerScore.get_high_scores(game, 5)
      elif board == 'today':
        scores, query = datamodel.PlayerScore.get_high_scores(game, 5, True)
      else:  # default to 'friends'
        scores, query = datamodel.PlayerScore.get_high_friend_scores(self.player.get_id(), game, 5)

    client_id = 'scoreboard' + self.player.get_id()
    event_hub.register_query(datamodel.PlayerEvent, query, client_id)
    token = ""
    if self.request.get('new_token'):
      token = channel.create_channel(client_id);
    self.response.out.write('%s|%s,' % (token, query))
    for (i, score) in enumerate(scores):
      alias = datamodel.Player.get(player_id=score.player_id).alias
      if cat == 'best_time':
        self.response.out.write('%s|%s|%s|%s|%s,' % (i + 1, score.player_id, alias, score.time, score.when))
      else:
        self.response.out.write('%s|%s|%s|%s|%s,' % (i + 1, score.player_id, alias, score.score, score.when))

  def list_players(self):
    for player in datamodel.Player.all().fetch(20):
      self.response.out.write('%s|%s,' % (player.alias, player.get_id()))

  def update_player(self):
    alias = self.request.get('alias')
    if not alias:
      self.response.set_status(400)
      self.response.out.write('Invalid Alias')
      return
    datamodel.Player.change_alias(self.player.get_id(), alias)

  def add_friend(self):
    email = self.request.get('email')
    friend_id = datamodel.Player.lookup_id(email=email)
    if not friend_id:
      self.response.set_status(400)
      self.response.out.write('Player not found')
      return

    error = datamodel.Friendship.add_friendship(self.player.get_id(), friend_id)
    if error:
      self.response.set_status(400)
      self.response.out.write(error)
      return

  def accept_friend(self):
    error = datamodel.Friendship.accept_friendship(self.player.get_id(),
                                                   self.request.get('friend_id'),
                                                   self.request.get('reference'))
    if error:
      self.response.set_status(400)
      self.response.out.write(error)
      return

  def remove_friend(self):
    error = datamodel.Friendship.remove_friendship(self.player.get_id(),
                                                   self.request.get('friend_id'),
                                                   self.request.get('reference'))
    if error:
      self.response.set_status(400)
      self.response.out.write(error)
      return

  def list_party_players(self):
    self.response.out.write('Players: %s' % self.party.get_player_list())

  def list_friends(self):
    for friendship in datamodel.Friendship.get_friendships(self.player.get_id()):
      friend = datamodel.Player.get(player_id=friendship.friend_id)
      if friend:
        self.response.out.write('%s|%s|%s|%s,' % (friend.alias,
                                                  friend.email,
                                                  friend.get_id(),
                                                  1))

    for friendship in datamodel.Friendship.get_pending_friendships(self.player.get_id()):
      friend = datamodel.Player.get(player_id=friendship.friend_id)
      if friend:
        self.response.out.write('%s|%s|%s|%s,' % (friend.alias,
                                                  friend.email,
                                                  friend.get_id(),
                                                  0))

  def get_safe(self, template_values):
    doa_name = self.request.get('name', '')
    action = self.request.get('action', '')
    fn = self.req_trans.get('%s-%s' % (doa_name, action), None)
    if fn:
      fn()
    else:
      self.response.set_status(400)
      self.response.out.write('Request not recognized')


class DashboardPage(RestrictedPage):
  def get_safe(self, template_values):
    template_values['alias'] = self.player.alias
    self.response.out.write(template.render('templates/dashboard.html', template_values))


class DebugPage(RestrictedPage):
  def get_safe(self, template_values):
    template_values['alias'] = self.player.alias
    self.response.out.write(template.render('templates/debug_panel.html', template_values))


class PlayerSetupPage(RestrictedPage):
  def get_safe(self, template_values):
    template_values['alias'] = self.player.alias
    self.response.out.write(template.render('templates/player_setup.html', template_values))

class EventMatchResults(webapp.RequestHandler):
  def post(self):
    sub_ids = self.request.get_all('id')
#    key = self.request.get('key')
#    topic = self.request.get('topic')
#    results_count = self.request.get('results_count')
#    results_offset = self.request.get('results_offset')
    event = prospective_search.get_document(self.request)
    event_hub.handle_query_matches(sub_ids, event)



class ScoreBoardPage(RestrictedPage):
  def get_safe(self, template_values):
    self.response.out.write(template.render('templates/score_board.html', template_values))

application = webapp.WSGIApplication([
                                      ('/dash', DashboardPage),
                                      ('/psetup', PlayerSetupPage),
                                      ('/dao', DaoPage),
                                      ('/debug', DebugPage),
                                      ('/score', ScoreBoardPage),
                                      ('/_ah/prospective_search', EventMatchResults),
                                      ('/', MainPage)], debug=True)


def main():
    run_wsgi_app(application)


if __name__ == "__main__":
    main()
